package xyz.lwm.lazycat.utility;

import xyz.lwm.lazycat.utility.exception.LazycatException;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * throwable util
 *
 * @author lwm
 */
public abstract class ThrowableUtil {

    /**
     * print throwable to string
     *
     * @param throwable throwable
     * @return string
     */
    public static String print(Throwable throwable) {
        StringWriter sw = new StringWriter();
        print(throwable, sw);
        return sw.toString();
    }

    /**
     * print throwable to writer
     *
     * @param throwable throwable
     * @param writer    writer
     */
    public static void print(Throwable throwable, Writer writer) {
        throwable.printStackTrace(new PrintWriter(writer));
    }

    /**
     * wrap throwable to lazycat exception
     *
     * @param throwable throwable
     * @return lazycat exception
     */
    public static LazycatException wrap(Throwable throwable) {
        if (throwable instanceof LazycatException) {
            return (LazycatException) throwable;
        }
        return new LazycatException(throwable);
    }

    /**
     * unwrap throwable
     *
     * @param throwable throwable
     * @return original throwable
     */
    public static Throwable unwrap(Throwable throwable) {
        Throwable unwrapped = throwable;

        while (true) {
            if (unwrapped instanceof InvocationTargetException) {
                unwrapped = ((InvocationTargetException) unwrapped).getTargetException();

            } else if (unwrapped instanceof UndeclaredThrowableException) {
                unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();

            } else if (unwrapped instanceof RuntimeException && unwrapped.getCause() != null) {
                unwrapped = unwrapped.getCause();

            } else {
                return unwrapped;
            }
        }
    }

}
